package stack

import (
	"jvm/nzpJvm/instructions/base"
	"jvm/nzpJvm/runtime_area"
)
// dup指令的宽索引版本，用于double和long
type DUP2 struct {
	base.NoOperandsInstruction
}
// 弹出一个，然后压入两次，相当于复制一次
func (self *DUP2) Execute(frame *runtime_area.Frame) {
	slotHigh := frame.OperandStack().PopSlot()
	slotLow := frame.OperandStack().PopSlot()

	frame.OperandStack().PushSlot(slotLow)
	frame.OperandStack().PushSlot(slotHigh)

	frame.OperandStack().PushSlot(slotLow)
	frame.OperandStack().PushSlot(slotHigh)
}

// 复制栈顶数值并将两个复制值推入栈顶。宽索引版本，用于double和long
type DUP2_X1 struct {
	base.NoOperandsInstruction
}

func (self *DUP2_X1) Execute(frame *runtime_area.Frame) {
	slotHigh := frame.OperandStack().PopSlot()
	slotLow := frame.OperandStack().PopSlot()

	frame.OperandStack().PushSlot(slotLow)
	frame.OperandStack().PushSlot(slotHigh)

	frame.OperandStack().PushSlot(slotLow)
	frame.OperandStack().PushSlot(slotHigh)

	frame.OperandStack().PushSlot(slotLow)
	frame.OperandStack().PushSlot(slotHigh)
}

// 复制栈顶数值并将三个复制值推入栈顶。宽索引版本，用于double和long
type DUP2_X2 struct {
	base.NoOperandsInstruction
}

func (self *DUP2_X2) Execute(frame *runtime_area.Frame) {
	slotHigh := frame.OperandStack().PopSlot()
	slotLow := frame.OperandStack().PopSlot()

	frame.OperandStack().PushSlot(slotLow)
	frame.OperandStack().PushSlot(slotHigh)

	frame.OperandStack().PushSlot(slotLow)
	frame.OperandStack().PushSlot(slotHigh)

	frame.OperandStack().PushSlot(slotLow)
	frame.OperandStack().PushSlot(slotHigh)

	frame.OperandStack().PushSlot(slotLow)
	frame.OperandStack().PushSlot(slotHigh)
}
